//
//  HZJTreeViewModelProtocol.swift
//  HZJTreeView
//
//  Created by 何治军 on 2020/6/18.
//  Copyright © 2020 何治军. All rights reserved.
//

import Foundation

///用于构造多级树
@objc protocol HZJTreeViewModelProtocol {
    /// 所属父数据(不用手动去设置，会根据setChildModels自动修改)
    var fatherModel:HZJTreeViewModelProtocol? { get set }
    
    /// 包含的子数据(需使用setChildModels方法赋值)
    var childModels:[HZJTreeViewModelProtocol] { get set }
}

//MARK: - 添加的非私有属性
extension HZJTreeViewModelProtocol {
    /// 是否展示当前项
    public var isShowCurrent:Bool {
        return self._isShow
    }

    /// 是否打开，以展示当前项的childModels
    public var isOpen:Bool {
        return self._isOpen
    }
    
    ///等级
    var type:Int{
        return self._type
    }
}

//MARK: -用于修改属性的方法
extension HZJTreeViewModelProtocol {
    @discardableResult
    public func toShowCurrent(_ show:Bool) -> HZJTreeViewModelProtocol{
        self._isShow = show
        return self
    }
    
    @discardableResult
    public func setOpenState(_ open:Bool) -> HZJTreeViewModelProtocol{
        self._isOpen = open
        return self
    }
}

//MARK: -其他重要的方法
extension HZJTreeViewModelProtocol {
    /// 设置子数据(注意不要循环引用了)
    /// - Parameter models: <#models description#>
    /// - Returns: <#description#>
    @discardableResult
    public func setChildModels(_ models:[HZJTreeViewModelProtocol]) -> [HZJTreeViewModelProtocol] {
        for item in models {
            item.fatherModel = self
            item._isShow = self.isOpen
        }
        self.childModels = models
        self.setAllChildModeType(self._type)
        return self.childModels
    }
    
    /// 修改当前childModels的展示状态
    /// - Parameter open: 是否展示
    /// - Parameter allChild: 是否针对所有子数据
    public func changeChildModelShowState(_ open:Bool, allChild:Bool = false) {
        self._isOpen = open
        for item in self.childModels {
            item._isShow = open
            if allChild {
                item.changeChildModelShowState(open, allChild: allChild)
            }
        }
    }
    
    /// 获取所有子数据(包括子数据的子数据的子数据...递归操作)
    /// - Returns: <#description#>
    public func getAllChildModel() -> [HZJTreeViewModelProtocol] {
        var result:[HZJTreeViewModelProtocol] = []
        for item in self.childModels {
            result.append(item)
            result.append(contentsOf: item.getAllChildModel())
        }
        return result
    }
    
    /// 获取需要展示所有子数据(包括子数据的子数据的子数据...递归操作,若父类 关闭，则不向下遍历)
    /// - Returns: <#description#>
    public func getAllShowChildModel() -> [HZJTreeViewModelProtocol] {
        var result:[HZJTreeViewModelProtocol] = []
        for item in self.childModels {
            if item.isShowCurrent {
                result.append(item)
            }
            if item._isOpen {
                result.append(contentsOf: item.getAllShowChildModel())
            }
        }
        return result
    }
}

//MARK: - 私有属性
private extension HZJTreeViewModelProtocol {
    /// 是否展示当前项
    var _isShow:Bool {
        set {
            objc_setAssociatedObject(self, AssociationKey.from(#function), newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
        get{
            guard let t = objc_getAssociatedObject(self,  AssociationKey.from(#function)) as? Bool else {
                return true//默认值
            }
            return t
        }
    }
    
    /// 是否打开，以展示当前项的childModels
    var _isOpen:Bool {
        set {
            objc_setAssociatedObject(self, AssociationKey.from(#function), newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
        get{
            guard let t = objc_getAssociatedObject(self,  AssociationKey.from(#function)) as? Bool else {
                return false//默认值
            }
            return t
        }
    }
    
    ///等级
    var _type:Int {
        set {
            objc_setAssociatedObject(self, AssociationKey.from(#function), newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
        get{
            guard let t = objc_getAssociatedObject(self,  AssociationKey.from(#function)) as? Int else {
                return 1//默认值
            }
            return t
        }
    }
}

//MARK: - 私有的方法
private extension HZJTreeViewModelProtocol{
    
    /// 递归设置子数据的type
    func setAllChildModeType(_ currentType:Int){
        for item in self.childModels {
            let type =  currentType + 1
            item._type = type
            item.setAllChildModeType(type)
        }
    }
}
